//package com.yjk1.example.myFirstSofawebBoot;
//
//import org.springframework.beans.factory.DisposableBean;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.beans.factory.config.BeanDefinition;
//import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
//import org.springframework.context.annotation.AnnotationConfigApplicationContext;
//import org.springframework.context.annotation.ScannedGenericBeanDefinition;
//import org.springframework.context.support.ClassPathXmlApplicationContext;
//import org.springframework.core.io.Resource;
//import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
//import org.springframework.core.io.support.ResourcePatternResolver;
//import org.springframework.core.type.AnnotationMetadata;
//import org.springframework.core.type.classreading.MetadataReader;
//import org.springframework.core.type.classreading.MetadataReaderFactory;
//import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
//import org.springframework.stereotype.Component;
//import org.springframework.stereotype.Controller;
//import org.springframework.stereotype.Service;
//import org.springframework.util.ReflectionUtils;
//import org.springframework.web.bind.annotation.RequestMapping;
//import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
//import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
//
//import java.io.File;
//import java.lang.reflect.Method;
//import java.lang.reflect.Modifier;
//import java.net.MalformedURLException;
//import java.net.URL;
//import java.net.URLClassLoader;
//import java.util.*;
//
//@Service
//public class LoadService {
//
//    @Autowired
//    private AnnotationConfigServletWebServerApplicationContext annotationConfigServletWebServerApplicationContext;
//
//    /**
//     * 保存对应的classLoader
//     */
//    public List<URLClassLoader> classLoaders = new ArrayList<>();
//
//    public Map<String, MyBizPluginManager> bizPluginManagerMap = new HashMap<>();
//
//    public Map<String, Map<String, Object>> bizPluginBeanObjs = new HashMap<>();
//
//    public void register(String jarPath, final String jarName) {
//        try {
//           /* String jarPath = "E:\\open-source-prj\\PluginBizTest\\target\\PluginBizTest-1.0-SNAPSHOT.jar";
//            file = new File(jarPath);
//            //查找依赖的jar包，同级目录下的lib/
//            List<URL> dependencyJar = findDependencyJar(file);*/
//
//            AnnotationConfigServletWebServerApplicationContext tempApplicationContext = annotationConfigServletWebServerApplicationContext;
//
///*            AnnotationConfigServletWebServerApplicationContext tempApplicationContext = new AnnotationConfigServletWebServerApplicationContext();
//            tempApplicationContext.setParent(annotationConfigServletWebServerApplicationContext);
//            tempApplicationContext.refresh();*/
//
//
//           /* URL[] urls = dependencyJar.toArray(new URL[dependencyJar.size()]);
//            //新建classloader 核心
//            URLClassLoader urlClassLoader = new URLClassLoader(urls, tempApplicationContext.getClassLoader());*/
//            MyBizPluginManager myBizPluginManager = new MyBizPluginManager();
//            myBizPluginManager.loadPlugin(jarPath, jarName, tempApplicationContext.getClassLoader());
//
//            bizPluginManagerMap.put(jarName, myBizPluginManager);
//
//            URLClassLoader urlClassLoader = myBizPluginManager.getClassLoaderByPluginName(jarName);
//            classLoaders.add(urlClassLoader);
//
//            //获取导入的jar的controller  service  dao 等类，并且创建BeanDefinition
//            Set<BeanDefinition> beanDefinitions = getBeanDefinitions(urlClassLoader);
//
//            beanDefinitions.forEach(item -> {
//                //根据beanDefinition通过BeanFactory注册bean
//                tempApplicationContext.getDefaultListableBeanFactory().registerBeanDefinition(item.getBeanClassName(), item);
//            });
//
//            //修改BeanFactory的ClassLoader
//            tempApplicationContext.getDefaultListableBeanFactory().setBeanClassLoader(urlClassLoader);
//            // 清除元数据缓存
//            tempApplicationContext.getDefaultListableBeanFactory().clearMetadataCache();
//            //获取requestMappingHandlerMapping，用来注册HandlerMapping
//            RequestMappingHandlerMapping requestMappingHandlerMapping = tempApplicationContext.getBean(RequestMappingHandlerMapping.class);
//            beanDefinitions.forEach(item -> {
//
//                String classname = item.getBeanClassName();
//                try {
//                    Class<?> c = Class.forName(classname, false, urlClassLoader);
//                    Controller annotation = c.getAnnotation(Controller.class);
//                    Object proxy = null;
//                    // 不是接口也不是抽象类
//                    if (!c.isInterface() && !Modifier.isAbstract(c.getModifiers())) {
//                        //获取该bean 真正的创建
//                        proxy = tempApplicationContext.getBean(item.getBeanClassName());
//                        Map<String, Object> jarBeanObjs = bizPluginBeanObjs.get(jarName);
//                        if (null == jarBeanObjs) {
//                            jarBeanObjs = new HashMap<>();
//                            bizPluginBeanObjs.put(jarName, jarBeanObjs);
//                        }
//                        jarBeanObjs.put(classname, proxy);
//                    }
//                    //如果此bean是Controller，则注册到RequestMappingHandlerMapping里面
//                    if (annotation != null) {
//
//                        Method getMappingForMethod = ReflectionUtils.findMethod(RequestMappingHandlerMapping.class, "getMappingForMethod", Method.class, Class.class);
//                        getMappingForMethod.setAccessible(true);
//                        try {
//                            Method[] method_arr = c.getMethods();
//                            for (Method m_d : method_arr) {
//                                if (m_d.getAnnotation(RequestMapping.class) != null) {
//                                    //创建RequestMappingInfo
//                                    RequestMappingInfo mapping_info = (RequestMappingInfo) getMappingForMethod.invoke(requestMappingHandlerMapping, m_d, c);
//                                    //注册
//                                    requestMappingHandlerMapping.registerMapping(mapping_info, proxy, m_d);
//                                }
//
//                            }
//
//                        } catch (Exception e) {
//                            e.printStackTrace();
//                        }
//
//                    }
//                } catch (ClassNotFoundException e) {
//                    e.printStackTrace();
//                }
//            });
//
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//
//    }
//
//    public void unregister(String pluginName) {
//
//        Map<String, Object> pluginBeanObjMap = bizPluginBeanObjs.get(pluginName);
//        if (null != pluginBeanObjMap) {
//            for (Map.Entry<String, Object> ele : pluginBeanObjMap.entrySet()) {
//                /*Object beanObj = ele.getValue();
//                if(beanObj instanceof DisposableBean){
//                    try {
//                        ((DisposableBean) beanObj).destroy();
//                    } catch (Exception e) {
//                        e.printStackTrace();
//                    }
//                }*/
//                // 卸载bean
//                annotationConfigServletWebServerApplicationContext.getDefaultListableBeanFactory().removeBeanDefinition(ele.getKey());
//            }
//            bizPluginBeanObjs.remove(pluginName);
//        }
//
//        MyBizPluginManager myBizPluginManager = bizPluginManagerMap.get(pluginName);
//        if (null != myBizPluginManager) {
//            myBizPluginManager.unloadPlugin(pluginName);
//            bizPluginManagerMap.remove(pluginName);
//        }
//    }
//
//    private static List<URL> findDependencyJar(File file) throws MalformedURLException {
//        List<URL> list = new ArrayList<>();
//        File parentFile = file.getParentFile();
//        File libFile = new File(file.getParent() + File.separator + "lib");
//        if (libFile.exists() && parentFile.isDirectory()) {
//            for (File jar : libFile.listFiles()) {
//                if (jar.isFile()
//                        && jar.getName().toLowerCase().endsWith(".jar")
//                        ) {
//                    list.add(jar.toURI().toURL());
//                }
//            }
//        }
//        list.add(file.toURI().toURL());
//        return list;
//
//    }
//
//
//    public Set<BeanDefinition> getBeanDefinitions(ClassLoader classLoader) throws Exception {
//        Set<BeanDefinition> candidates = new LinkedHashSet<>();
//
//        ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(classLoader);
//        Resource[] resources = resourcePatternResolver.getResources("classpath*:com/yjk/**/*.**");
//
//        MetadataReaderFactory metadata = new SimpleMetadataReaderFactory();
//        for (Resource resource : resources) {
//            MetadataReader metadataReader = metadata.getMetadataReader(resource);
//            ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
//            AnnotationMetadata metadata1 = sbd.getMetadata();
//            if (metadata1.isAbstract() || metadata1.isInterface() || metadata1.isAnnotation() ||
//                    ((null != metadata1.getEnclosingClassName() || "" != metadata1.getEnclosingClassName())
//                            && !metadata1.isIndependent())) {
//                continue;
//            }
//            sbd.setResource(resource);
//            sbd.setSource(resource);
//            candidates.add(sbd);
//        }
//        for (BeanDefinition beanDefinition : candidates) {
//            String classname = beanDefinition.getBeanClassName();
//            Controller c = Class.forName(classname, false, classLoader).getAnnotation(Controller.class);
//            Service s = Class.forName(classname, false, classLoader).getAnnotation(Service.class);
//            Component component = Class.forName(classname, false, classLoader).getAnnotation(Component.class);
//            if (c != null || s != null || component != null)
//                System.out.println(classname);
//        }
//
//        return candidates;
//    }
//
//}
